package club.jdiy.core.job.exec;

import club.jdiy.core.ex.JDiyException;
import club.jdiy.core.job.entity.JDiyJob;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;

import static club.jdiy.core.job.exec.JobHandler.TASK_PROPERTIES;

/**
 * 定时任务工具类
 *
 * @author ziquee(子秋) QQ号:39886616 主页: http://www.jdiy.club
 * @version 20210622
 */
@Slf4j
public class ScheduleUtils {

    public static void createScheduleJob(Scheduler scheduler, JDiyJob job) throws JDiyException {
        try {
            Class<? extends Job> jobClass = getJobClass(job);

            String jobName = job.getJobName();
            String jobGroup = job.getJobGroup();
            JobKey jobKey = getJobKey(job);
            TriggerKey triggerKey = getTriggerKey(jobName, jobGroup);


            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).build();

            // 构建调度
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getJobCron());
            cronScheduleBuilder = withMisfirePolicy(job, cronScheduleBuilder);

            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();

            // 放入参数，运行时的方法可以获取
            jobDetail.getJobDataMap().put(TASK_PROPERTIES, job);

            boolean isEdit;
            if (isEdit = scheduler.checkExists(jobKey)) {// 存在时为修改，先移除再加
                scheduler.deleteJob(jobKey);
            }

            scheduler.scheduleJob(jobDetail, trigger);

            // 暂停任务
            if (Boolean.TRUE.equals(job.getJobPause())) {
                scheduler.pauseJob(ScheduleUtils.getJobKey(job));
            }
            log.info(isEdit ?
                    jobName + "@" + jobGroup + " job updated. {" + job.getJobCron() + "}"
                    : jobName + "@" + jobGroup + " job created. {" + job.getJobCron() + "}"
            );
        } catch (SchedulerException ex) {
            ex.printStackTrace();
            throw new JDiyException(ex.getMessage(), ex.getCause());
        }
    }

    public static TriggerKey getTriggerKey(String jobName, String jobGroup) {
        return TriggerKey.triggerKey(jobName + "_trigger", jobGroup + "_trigger");
    }

    public static JobKey getJobKey(JDiyJob job) {
        return JobKey.jobKey(job.getJobName(), job.getJobGroup());
    }

    private static CronScheduleBuilder withMisfirePolicy(JDiyJob job, CronScheduleBuilder cb) {
        if (job.getJobMisfire() == null) return cb;
        switch (job.getJobMisfire()) {
            case 1:
                return cb.withMisfireHandlingInstructionIgnoreMisfires();
            case 2:
                return cb.withMisfireHandlingInstructionFireAndProceed();
            case 3:
                return cb.withMisfireHandlingInstructionDoNothing();
            default:
                return cb;
        }
    }

    private static Class<? extends Job> getJobClass(JDiyJob JDiyJob) {
        return Boolean.TRUE.equals(JDiyJob.getJobConcurrent()) ? JobBaseHandler.class : JobDescHandler.class;
    }
}